package com.hnxxxy.oa.system.aspect;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hnxxxy.oa.annotation.SysLog;
import com.hnxxxy.oa.system.model.SysOperateLogDO;
import com.hnxxxy.oa.system.model.SysUserDO;
import com.hnxxxy.oa.system.service.SysLoginLogService;
import com.hnxxxy.oa.system.service.SysOperateLogService;
import com.hnxxxy.oa.system.service.SysUserService;
import com.hnxxxy.oa.utils.R;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;

/**
 * @author ZHOUSHILIN
 * @data 2022 - 05 - 14 - 10:49
 */
@Aspect
@Component
public class SysLogAspect {

    @Resource
    private SysLoginLogService sysLoginLogService;

    @Resource
    private SysOperateLogService sysOperateLogService;

    @Resource
    private SysUserService sysUserService;

    @Pointcut("@annotation(com.hnxxxy.oa.annotation.SysLog)")
    public void logPointCut() {

    }
    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        Object result=null;
        Exception exception=null;
        //执行方法
        try {
            result = point.proceed();
        }catch (Exception e){
            exception=e;
        }
        if (result==null){
            saveFailSysLog(point,exception);
            return R.buildError(exception.getMessage());
        }
        saveSuccessSysLog(point, result);
        return result;
    }

    private void saveFailSysLog(ProceedingJoinPoint joinPoint, Exception e) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        SysOperateLogDO sysLog = new SysOperateLogDO();

        SysLog syslog = method.getAnnotation(SysLog.class);
        if(syslog != null){
            //注解上的描述
            sysLog.setRemark(syslog.value());
        }

        //请求的方法名
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        Object loginId=null;
        try {
            loginId = StpUtil.getLoginId();
        }catch (Exception exception){
            sysLog.setBusinessName(className);
            sysLog.setMethodName(methodName);

            //请求的参数
            Object[] args = joinPoint.getArgs();
            String s = Arrays.toString(args);
            sysLog.setHttpParam(JSONUtil.toJsonStr(s));

            //获取request
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            //设置IP地址
            sysLog.setIp(sysLoginLogService.getIpAddr(request));
            sysLog.setLogStatus(0);
            sysLog.setError(e.getMessage());
            sysLog.setResult(e.toString());
            //保存系统日志
            sysOperateLogService.insert(sysLog);
            return;
        }
        int userId=Integer.parseInt(loginId.toString());
        sysLog.setOperateId(userId);
        SysUserDO sysUserDO = sysUserService.selectUserById(userId);
        sysLog.setUsername(sysUserDO.getUsername());
        sysLog.setBusinessName(className);
        sysLog.setMethodName(methodName);

        //请求的参数
        Object[] args = joinPoint.getArgs();
        String s = Arrays.toString(args);
        sysLog.setHttpParam(JSONUtil.toJsonStr(s));

        //获取request
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //设置IP地址
        sysLog.setIp(sysLoginLogService.getIpAddr(request));
        sysLog.setLogStatus(0);
        sysLog.setError(e.getMessage());
        sysLog.setResult(e.toString());
        //保存系统日志
        sysOperateLogService.insert(sysLog);
    }


    private void saveSuccessSysLog(ProceedingJoinPoint joinPoint, Object result) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        SysOperateLogDO sysLog = new SysOperateLogDO();

        SysLog syslog = method.getAnnotation(SysLog.class);
        if(syslog != null){
            //注解上的描述
            sysLog.setRemark(syslog.value());
        }

        //请求的方法名
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        sysLog.setBusinessName(className);
        sysLog.setMethodName(methodName);
        if (!"userRegister".equals(methodName)&&!"userLogout".equals(methodName)){
            int userId=Integer.parseInt(StpUtil.getLoginId().toString());
            sysLog.setOperateId(userId);
            SysUserDO sysUserDO = sysUserService.selectUserById(userId);
            sysLog.setUsername(sysUserDO.getUsername());
        }
        if ("userLogout".equals(methodName)){
            if (result instanceof R){
                int userId=Integer.parseInt(((R) result).getData().toString());
                sysLog.setOperateId(userId);
                SysUserDO sysUserDO = sysUserService.selectUserById(userId);
                sysLog.setUsername(sysUserDO.getUsername());
            }
        }
        //请求的参数
        Object[] args = joinPoint.getArgs();
        String s = Arrays.toString(args);
        sysLog.setHttpParam(JSONUtil.toJsonStr(s));

        //获取request
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //设置IP地址
        sysLog.setIp(sysLoginLogService.getIpAddr(request));
        sysLog.setLogStatus(1);
        sysLog.setResult(result.toString());
        //保存系统日志
        sysOperateLogService.insert(sysLog);
    }
}
